package com.hsu.apibackend.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hsu.apibackend.annotation.AuthCheck;
import com.hsu.apibackend.common.*;
import com.hsu.apibackend.constant.CommonConstant;
import com.hsu.apibackend.exception.BusinessException;
import com.hsu.apibackend.model.dto.productinfo.ProductInfoAddRequest;
import com.hsu.apibackend.model.dto.productinfo.ProductInfoQueryRequest;
import com.hsu.apibackend.model.dto.productinfo.ProductInfoSearchTextRequest;
import com.hsu.apibackend.model.dto.productinfo.ProductInfoUpdateRequest;
import com.hsu.apibackend.model.entity.ProductInfo;
import com.hsu.apibackend.model.enums.ProductInfoStatusEnum;
import com.hsu.apibackend.model.vo.UserVO;
import com.hsu.apibackend.service.ProductInfoService;
import com.hsu.apibackend.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

import static com.hsu.apibackend.constant.UserConstant.ADMIN_ROLE;

/**
 * @Author Hsu琛君珩
 * @Date 2024-09-10 14:31
 * @Description 产品信息接口
 * @Version: v1.0.0
 */
@RestController
@RequestMapping("/productInfo")
@Slf4j
public class ProductInfoController {

    @Resource
    private ProductInfoService productInfoService;

    @Resource
    private UserService userService;

    /**
     * 添加产品信息
     * 创建产品信息记录
     *
     * @param productInfoAddRequest 产品信息添加请求
     * @param request               请求对象，包含用户登录信息
     * @return {@link BaseResponse}<{@link Long}> 返回创建的产品信息ID
     */
    @PostMapping("/add")
    @AuthCheck(mustRole = ADMIN_ROLE)
    public BaseResponse<Long> addProductInfo(@RequestBody ProductInfoAddRequest productInfoAddRequest, HttpServletRequest request) {
        // 校验请求参数是否为空
        if (productInfoAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 创建并复制请求参数到产品信息实体
        ProductInfo productInfo = new ProductInfo();
        BeanUtils.copyProperties(productInfoAddRequest, productInfo);

        // 验证产品信息的合法性
        productInfoService.validProductInfo(productInfo, true);

        // 获取当前登录的用户信息
        UserVO loginUser = userService.getLoginUser(request);
        productInfo.setUserId(loginUser.getId());

        // 保存产品信息到数据库
        boolean result = productInfoService.save(productInfo);

        // 如果保存失败，抛出操作错误
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }

        // 返回新创建的产品信息ID
        long newProductInfoId = productInfo.getId();
        return ResultUtils.success(newProductInfoId);
    }

    /**
     * 删除产品信息
     * 仅管理员或产品创建者可以删除
     *
     * @param deleteRequest 删除请求，包含产品信息ID
     * @param request       请求对象，包含用户登录信息
     * @return {@link BaseResponse}<{@link Boolean}> 返回删除操作是否成功
     */
    @PostMapping("/delete")
    @AuthCheck(mustRole = ADMIN_ROLE)
    public BaseResponse<Boolean> deleteProductInfo(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        // 校验删除请求参数是否合法
        if (ObjectUtils.anyNull(deleteRequest, deleteRequest.getId()) || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 获取当前登录的用户信息
        UserVO user = userService.getLoginUser(request);
        long id = deleteRequest.getId();

        // 检查产品信息是否存在
        ProductInfo oldProductInfo = productInfoService.getById(id);
        if (oldProductInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 判断是否是产品的拥有者或管理员，只有他们才可以删除
        if (!oldProductInfo.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        // 执行删除操作
        boolean b = productInfoService.removeById(id);

        // 返回删除结果
        return ResultUtils.success(b);
    }

    /**
     * 更新产品信息
     * 仅管理员或产品的创建者可以更新产品信息
     *
     * @param productInfoUpdateRequest 产品信息更新请求
     * @param request                  请求对象，包含用户登录信息
     * @return {@link BaseResponse}<{@link Boolean}> 返回更新操作是否成功
     */
    @PostMapping("/update")
    @AuthCheck(mustRole = ADMIN_ROLE)
    @Transactional(rollbackFor = Exception.class) // 如果发生异常，事务将回滚
    public BaseResponse<Boolean> updateProductInfo(@RequestBody ProductInfoUpdateRequest productInfoUpdateRequest,
                                                   HttpServletRequest request) {
        // 校验请求参数
        if (ObjectUtils.anyNull(productInfoUpdateRequest, productInfoUpdateRequest.getId()) || productInfoUpdateRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 将 DTO 转换为 ProductInfo 实体类
        ProductInfo productInfo = new ProductInfo();
        BeanUtils.copyProperties(productInfoUpdateRequest, productInfo);

        // 校验产品信息参数
        productInfoService.validProductInfo(productInfo, false);

        // 获取当前登录的用户信息
        UserVO user = userService.getLoginUser(request);
        long id = productInfoUpdateRequest.getId();

        // 判断要更新的产品信息是否存在
        ProductInfo oldProductInfo = productInfoService.getById(id);
        if (oldProductInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 仅产品创建者或管理员可以修改
        if (!userService.isAdmin(request) && !oldProductInfo.getUserId().equals(user.getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        // 更新产品信息
        boolean result = productInfoService.updateById(productInfo);

        // 返回操作结果
        return ResultUtils.success(result);
    }

    /**
     * 通过id获取产品信息
     *
     * @param id id
     * @return {@link BaseResponse}<{@link ProductInfo}>
     */
    @GetMapping("/get")
    public BaseResponse<ProductInfo> getProductInfoById(long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 根据ID获取产品信息
        ProductInfo productInfo = productInfoService.getById(id);
        return ResultUtils.success(productInfo);
    }

    /**
     * 获取产品信息列表（仅管理员可使用）
     *
     * @param productInfoQueryRequest 产品信息查询请求
     * @return {@link BaseResponse}<{@link List}<{@link ProductInfo}>>
     */
    @AuthCheck(mustRole = ADMIN_ROLE)
    @GetMapping("/list")
    public BaseResponse<List<ProductInfo>> listProductInfo(ProductInfoQueryRequest productInfoQueryRequest) {
        // 检查查询请求是否为空
        if (productInfoQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 将查询请求的属性拷贝到新的产品信息对象中
        ProductInfo productInfoQuery = new ProductInfo();
        BeanUtils.copyProperties(productInfoQueryRequest, productInfoQuery);

        // 构建查询条件
        QueryWrapper<ProductInfo> queryWrapper = new QueryWrapper<>(productInfoQuery);
        List<ProductInfo> productInfoList = productInfoService.list(queryWrapper);

        // 返回查询结果
        return ResultUtils.success(productInfoList);
    }

    /**
     * 分页获取产品信息列表
     *
     * @param productInfoQueryRequest 产品信息查询请求
     * @param request                 请求对象，包含用户登录信息
     * @return {@link BaseResponse}<{@link Page}<{@link ProductInfo}>>
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<ProductInfo>> listProductInfoByPage(ProductInfoQueryRequest productInfoQueryRequest, HttpServletRequest request) {
        // 检查请求是否为空
        if (productInfoQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 将查询请求的属性拷贝到新的产品信息对象中
        ProductInfo productInfoQuery = new ProductInfo();
        BeanUtils.copyProperties(productInfoQueryRequest, productInfoQuery);

        // 获取分页和排序参数
        long size = productInfoQueryRequest.getPageSize();
        String sortField = productInfoQueryRequest.getSortField();
        String sortOrder = productInfoQueryRequest.getSortOrder();
        String name = productInfoQueryRequest.getName();
        long current = productInfoQueryRequest.getCurrent();
        String description = productInfoQueryRequest.getDescription();
        String productType = productInfoQueryRequest.getProductType();
        Integer addPoints = productInfoQueryRequest.getAddPoints();
        Integer total = productInfoQueryRequest.getTotal();

        // 限制分页大小
        if (size > 50) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 构建查询条件
        QueryWrapper<ProductInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(name), "name", name)
                .like(StringUtils.isNotBlank(description), "description", description)
                .eq(StringUtils.isNotBlank(productType), "productType", productType)
                .eq(ObjectUtils.isNotEmpty(addPoints), "addPoints", addPoints)
                .eq(ObjectUtils.isNotEmpty(total), "total", total);

        // 根据字段排序（默认升序）
        queryWrapper.orderByAsc("total");

        // 执行分页查询
        Page<ProductInfo> productInfoPage = productInfoService.page(new Page<>(current, size), queryWrapper);

        // 如果不是管理员，仅返回状态为上线的产品信息
        if (!userService.isAdmin(request)) {
            List<ProductInfo> productInfoList = productInfoPage.getRecords().stream()
                    .filter(productInfo -> productInfo.getStatus().equals(ProductInfoStatusEnum.ONLINE.getValue()))
                    .collect(Collectors.toList());
            productInfoPage.setRecords(productInfoList);
        }

        // 返回分页结果
        return ResultUtils.success(productInfoPage);
    }

    /**
     * 按搜索文本分页获取产品信息列表
     *
     * @param productInfoQueryRequest 产品信息查询请求，包含分页和搜索文本等参数
     * @param request                 请求对象，包含用户登录信息
     * @return {@link BaseResponse}<{@link Page}<{@link ProductInfo}>>
     */
    @GetMapping("/get/searchText")
    public BaseResponse<Page<ProductInfo>> listProductInfoBySearchTextPage(ProductInfoSearchTextRequest productInfoQueryRequest, HttpServletRequest request) {
        // 校验请求是否为空
        if (productInfoQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 将请求中的查询参数拷贝到新的产品信息对象中
        ProductInfo productInfoQuery = new ProductInfo();
        BeanUtils.copyProperties(productInfoQueryRequest, productInfoQuery);

        // 获取搜索文本和分页参数
        String searchText = productInfoQueryRequest.getSearchText();
        long size = productInfoQueryRequest.getPageSize();
        long current = productInfoQueryRequest.getCurrent();
        String sortField = productInfoQueryRequest.getSortField();
        String sortOrder = productInfoQueryRequest.getSortOrder();

        // 构建查询条件，按名称和描述字段进行模糊查询
        QueryWrapper<ProductInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(searchText), "name", searchText)
                .or()
                .like(StringUtils.isNotBlank(searchText), "description", searchText);

        // 根据传入的排序字段和排序顺序进行排序
        queryWrapper.orderBy(StringUtils.isNotBlank(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);

        // 执行分页查询
        Page<ProductInfo> productInfoPage = productInfoService.page(new Page<>(current, size), queryWrapper);

        // 如果不是管理员，仅返回状态为上线的产品信息
        if (!userService.isAdmin(request)) {
            List<ProductInfo> productInfoList = productInfoPage.getRecords().stream()
                    .filter(productInfo -> productInfo.getStatus().equals(ProductInfoStatusEnum.ONLINE.getValue()))
                    .collect(Collectors.toList());
            productInfoPage.setRecords(productInfoList);
        }

        // 返回分页结果
        return ResultUtils.success(productInfoPage);
    }

    /**
     * 发布产品信息
     * 仅管理员可以将产品信息状态改为上线
     *
     * @param idRequest id请求，包含产品信息的ID
     * @return {@link BaseResponse}<{@link Boolean}> 返回发布操作是否成功
     */
    @AuthCheck(mustRole = ADMIN_ROLE)
    @PostMapping("/online")
    public BaseResponse<Boolean> onlineProductInfo(@RequestBody IdRequest idRequest) {
        // 校验ID请求参数是否合法
        if (ObjectUtils.anyNull(idRequest, idRequest.getId()) || idRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 根据ID获取产品信息
        Long id = idRequest.getId();
        ProductInfo productInfo = productInfoService.getById(id);
        if (productInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 将产品信息状态设置为上线
        productInfo.setStatus(ProductInfoStatusEnum.ONLINE.getValue());

        // 更新产品信息，并返回更新结果
        return ResultUtils.success(productInfoService.updateById(productInfo));
    }

    /**
     * 下线产品信息
     * 仅管理员可以将产品信息状态改为下线
     *
     * @param idRequest id请求，包含产品信息的ID
     * @return {@link BaseResponse}<{@link Boolean}> 返回下线操作是否成功
     */
    @PostMapping("/offline")
    @AuthCheck(mustRole = ADMIN_ROLE)
    public BaseResponse<Boolean> offlineProductInfo(@RequestBody IdRequest idRequest) {
        // 校验ID请求参数是否合法
        if (ObjectUtils.anyNull(idRequest, idRequest.getId()) || idRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 根据ID获取产品信息
        Long id = idRequest.getId();
        ProductInfo productInfo = productInfoService.getById(id);
        if (productInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 将产品信息状态设置为下线
        productInfo.setStatus(ProductInfoStatusEnum.OFFLINE.getValue());

        // 更新产品信息，并返回更新结果
        return ResultUtils.success(productInfoService.updateById(productInfo));
    }

    // endregion
}
